import { is } from '@electron-toolkit/utils';
import { app, BrowserWindow, BrowserWindowConstructorOptions } from 'electron';
import { resolve } from 'path';
import icon from '../../../resources/icon.png?asset'

export type WindowPoolOptions = BrowserWindowConstructorOptions & {
  url: string,
  brandNew?: boolean,
}

const COMMON_WINDOW_OPTIONS: BrowserWindowConstructorOptions = {
  width: 900,
  height: 670,
  show: false,
  frame: false,
  // transparent: true,
  icon,
  autoHideMenuBar: true,
  webPreferences: {
    preload: resolve(__dirname, '../preload/index.js'),
    sandbox: false
  }
}

export const getOpenUrl = (url:string): string => {
  const baseUrl =
    (is.dev && process.env['ELECTRON_RENDERER_URL'])
    ? process.env['ELECTRON_RENDERER_URL']
      : `file:///${resolve(__dirname, "../renderer/index.html")}`;;
  const newUrl = url.startsWith('http') ? url : `${baseUrl}#${url}`;
  return newUrl;
}

class WindowPoolManager {
  private static instance: WindowPoolManager;
  private windowPoolSize: number;
  private windowPools: Map<string, BrowserWindow>;

  private constructor(poolSize: number) {
    this.windowPoolSize = poolSize;
    this.windowPools = new Map<string, BrowserWindow>();
    this.initPool();
    app.on('quit', () => {
      this.windowPools.forEach((win) => {
        win.destroy();
      });
    })
  }

  public static getInstance(poolSize: number = 2): WindowPoolManager {
    if (!WindowPoolManager.instance) {
      WindowPoolManager.instance = new WindowPoolManager(poolSize);
    }
    return WindowPoolManager.instance;
  }

  private createPoolWindow(windowOptions: WindowPoolOptions): { id: string, win: BrowserWindow } {
    const win = new BrowserWindow({ ...windowOptions, show: false });
    win.on('maximize', () => {
      win.webContents.send('application:toggle-maximize-window', true);
    })
    win.on('unmaximize', () => {
      win.webContents.send('application:toggle-maximize-window', false)
    })
    const idData = windowOptions.url;
    const newUrl = getOpenUrl(windowOptions.url);
    win.loadURL(newUrl);
    this.windowPools.set(idData, win);
    return {
      id: idData,
      win,
    };
  }

  private initPool(): void {
    for (let i = 0; i < this.windowPoolSize; i++) {
      this.createPoolWindow({
        ...COMMON_WINDOW_OPTIONS,
        url: `/preload/${i}`, // 使用占位符 URL
      });
    }
  }

  private usePreWindow(): { id: string, win: BrowserWindow } | null {
    const preWindowKey = Array.from(this.windowPools.keys()).find((key) => key.startsWith('/preload') && this.windowPools.get(key)?.isVisible() === false);
    if (preWindowKey) {
      const preWindow = this.windowPools.get(preWindowKey);
      if (preWindow) {
        this.windowPools.delete(preWindowKey);
        return {
          id: preWindowKey,
          win: preWindow,
        };
      }
    }
    return null;
  }

  private checkCleanPool(): void {
    if (!this.windowPools.values().some((win) => !win.isDestroyed() && win.isVisible())) {
      if (process.platform !== 'darwin') {
        this.windowPools.forEach((win) => {
          win.destroy();
        });
        app.quit();
      }
    }
  }


  private withWindowOptions(win: BrowserWindow, windowOptions: WindowPoolOptions): void {
    win.setSize(windowOptions.width!, windowOptions.height!);
    if (Reflect.has(windowOptions, 'resizable')) {
      win.setResizable(windowOptions.resizable!);
    }
    if (Reflect.has(windowOptions, 'autoHideMenuBar')) {
      win.setAutoHideMenuBar(windowOptions.autoHideMenuBar!);
    }
  }

  public openWindow(windowOptions: WindowPoolOptions): BrowserWindow {
    let windowEntry: { id: string, win: BrowserWindow } | null = null;
    const idData = windowOptions.url;
    console.log("open-window", idData)
    if (idData && this.windowPools.has(idData) && !windowOptions.brandNew) {
      const win = this.windowPools.get(idData);
      if (win) {
        win.show();
        win.moveTop();
        win.focus();
        return win;
      }
    } else {
      windowEntry = this.usePreWindow();
    }

    if (!windowEntry) {
      windowEntry = this.createPoolWindow(windowOptions);
    } else {
      this.withWindowOptions(windowEntry.win, windowOptions);
    }

    const { win } = windowEntry;
    win.moveTop();
    win.focus();
    win.loadURL(windowOptions.url);
    win.on('ready-to-show', () => {
      win.show()
    })

    this.windowPools.set(idData, win);

    win.on('closed', () => {
      this.windowPools.delete(idData);
      this.ensurePreWindowPool();
      this.checkCleanPool();
    })

    this.ensurePreWindowPool();
    return win;
  }

  private ensurePreWindowPool(): void {
    const currentPreWindowCount = Array.from(this.windowPools.keys()).filter((key) => key.startsWith('/preload')).length;
    if (currentPreWindowCount < this.windowPoolSize) {
      this.createPoolWindow({
        ...COMMON_WINDOW_OPTIONS,
        url: `/preload/${currentPreWindowCount + 1}`,
      });
    }
  }
}

export default WindowPoolManager;
